package com.org.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.org.DTO.CollectItemsDTO;
import com.org.DTO.PageDTO;
import com.org.clients.HttpClient;
import com.org.context.BaseContext;
import com.org.entity.CollectItems;
import com.org.entity.SearchItems;
import com.org.exception.BaseException;
import com.org.exception.ServerException;
import com.org.mapper.CollectItemsMapper;
import com.org.message.BaseMessage;
import com.org.properties.RedisKeyPropertis;
import com.org.service.CollectItemsService;
import com.org.vo.PageResult;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.HashMap;

@Service
@Slf4j
@RequiredArgsConstructor
public class CollectItemsServiceImpl extends ServiceImpl<CollectItemsMapper, CollectItems> implements CollectItemsService {

    private final CollectItemsMapper collectItemsMapper;

    private final String BACKUP_COLLECT_ITEMS_URL = "http://localhost:8080/pc/backup/addCollectItems";

    private final StringRedisTemplate stringRedisTemplate;


    /**
     * 分页查询所有失物招领
     * @param pageDTO
     * @return
     */
    @Override
    public PageResult findAllPage(PageDTO pageDTO) {
        //1.参数校验
        if(pageDTO.getRegionId() == null){
            throw new BaseException(BaseMessage.SELECT_ERROR);
        }
        //1.分页
        Page<CollectItems> page = lambdaQuery()
                .eq(CollectItems::getRegionId, pageDTO.getRegionId())
                .eq(pageDTO.getStatus() != null, CollectItems::getStatus, pageDTO.getStatus())
                .eq(pageDTO.getIsMe() == 0, CollectItems::getUserId, BaseContext.getCurrentId())
                .page(new Page<>(pageDTO.getPageNum(), pageDTO.getPageSize()));
        return new PageResult(page.getTotal(), page.getRecords());
    }

    /**
     * 添加失物招领
     * @param collectItemsDTO
     */
    @Override
    public void addCollectItems(CollectItemsDTO collectItemsDTO) {
        //1、格式校验
        //1.1、手机号验证
        if(!collectItemsDTO.getPhone().matches("^1[3-9]\\d{9}$")){
            throw new BaseException(BaseMessage.PHONE_ERROR);
        }
        CollectItems collectItems = new CollectItems();
        BeanUtils.copyProperties(collectItemsDTO, collectItems);
        collectItems.setCreateTime(LocalDateTime.now());
        collectItems.setUpdateTime(LocalDateTime.now());
        collectItems.setUserId(BaseContext.getCurrentId());
        //2.添加
        int index = collectItemsMapper.insert(collectItems);
        if(index != 0){
            //3.添加到Redis
            stringRedisTemplate.opsForSet().add(RedisKeyPropertis.REDIS_KEY_UP_USE, collectItems.getImage());
        }
    }

    /**
     * 根据Id查询失物招领
     * @param id
     * @return
     */
    @Override
    public CollectItems findCollectItemsById(Long id) {
        //1.参数校验
        verifyId(id);
        //2.查询并返回
        return collectItemsMapper.selectById(id);
    }

    /**
     * 修改失物招领
     * @param collectItemsDTO
     */
    @Override
    public void updateCollectItems(CollectItemsDTO collectItemsDTO) {
        //1.参数校验
        verifyId(collectItemsDTO.getId());
        //2、格式校验
        //2.1、手机号验证
        if(collectItemsDTO.getPhone() != null){
            if(!collectItemsDTO.getPhone().matches("^1[3-9]\\d{9}$")){
                throw new BaseException(BaseMessage.PHONE_ERROR);
            }
        }
        //2.修改
        CollectItems collectItems = new CollectItems();
        BeanUtils.copyProperties(collectItemsDTO,collectItems);
        collectItems.setUpdateTime(LocalDateTime.now());
        //2.1、构建SQL
        LambdaUpdateWrapper<CollectItems> uw = new LambdaUpdateWrapper<CollectItems>()
                .set(collectItems.getItemName() != null && !collectItems.getItemName().isEmpty(),
                        CollectItems::getItemName, collectItems.getItemName())
                .set(collectItems.getPhone() != null && !collectItems.getPhone().isEmpty(),
                        CollectItems::getPhone, collectItems.getPhone())
                .set(collectItems.getDescribe() != null && !collectItems.getDescribe().isEmpty(),
                        CollectItems::getDescribe, collectItems.getDescribe())
                .set(collectItems.getImage() != null && !collectItems.getImage().isEmpty(),
                        CollectItems::getImage, collectItems.getImage())
                .set(collectItems.getRegionId() != null,
                        CollectItems::getRegionId, collectItems.getRegionId())
                .set(collectItems.getStatus() != null, CollectItems::getStatus, collectItems.getStatus())
                .set(collectItems.getUserId() != null,
                        CollectItems::getUserId, collectItems.getUserId())
                .set(collectItems.getTemporaryStorage() != null && !collectItems.getTemporaryStorage().isEmpty(),
                        CollectItems::getTemporaryStorage, collectItems.getTemporaryStorage())
                .set(collectItems.getCreateTime() != null,
                        CollectItems::getCreateTime, collectItems.getCreateTime())
                .eq(CollectItems::getId, collectItemsDTO.getId());

        //2.2、判断图片是否需要修改
        if(collectItems.getImage() != null && !collectItems.getImage().isEmpty()){
            //2.2.1、查询旧数据
            CollectItems oldCollectItems = collectItemsMapper.selectById(collectItems.getId());
            //2.2.2、修改数据并拿到执行结果
            boolean ifUpdate = update(uw);
            if(ifUpdate){
                //3、删除redis中的旧图片
                stringRedisTemplate.opsForSet().remove(RedisKeyPropertis.REDIS_KEY_UP_USE, oldCollectItems.getImage());
                //4、添加新图片到Redis
                stringRedisTemplate.opsForSet().add(RedisKeyPropertis.REDIS_KEY_UP_USE, collectItems.getImage());
            }
        }else{
            //2.3、修改数据
            update(uw);
        }
    }

    /**
     * 删除失物招领
     * @param id
     */
    @Override
    @Transactional
    public void deleteCollectItems(Long id) {
        //1.参数校验
        verifyId(id);
        //2、查询数据，用于备份
        CollectItems collectItems = collectItemsMapper.selectById(id);
        //3.删除
        if(collectItems == null){
            throw new BaseException(BaseMessage.DELETE_ERROR);
        }
        collectItemsMapper.deleteById(id);
        log.info("删除成功,删除的失物招领ID为{}", id);
        //4.备份
        //4.1、遍历collectItems，构建HashMap
        HashMap<String, String> paramMap = new HashMap<>();
        paramMap.put("collectItemsId", collectItems.getId().toString());
        paramMap.put("itemName", collectItems.getItemName());
        paramMap.put("image", collectItems.getImage());
        paramMap.put("describe", collectItems.getDescribe());
        paramMap.put("phone", collectItems.getPhone());
        paramMap.put("temporaryStorage", collectItems.getTemporaryStorage());
        paramMap.put("userId", collectItems.getUserId().toString());
        paramMap.put("regionId", collectItems.getRegionId().toString());
        paramMap.put("status", "2");
        try {
            HttpClient.doPost4Json(BACKUP_COLLECT_ITEMS_URL, paramMap, BaseContext.getThreadLocalToken());
        } catch (IOException e) {
            log.error("备份失物招领请求失败,异常信息为", e);
            throw new ServerException(BaseMessage.SERVER_ERROR);
        }
    }

    /**
     * 修改状态
     * @param id
     * @param status
     */
    @Override
    public void updateStatus(Long id, Long status) {
        //1.参数校验
        verifyId(id);
        verifyId(status);
        //2.修改
        LambdaUpdateWrapper<CollectItems> uw = new LambdaUpdateWrapper<CollectItems>()
                .eq(CollectItems::getId, id)
                .set(CollectItems::getStatus, status);
        collectItemsMapper.update(uw);
    }

    /**
     * 参数校验
     * @param id
     */
    private static void verifyId(Long id) {
        if(id == null){
            throw new BaseException(BaseMessage.INVALID_MESSAGE);
        }
    }

}
